/*
 * Platforma.cpp
 *
 *  Created on: 2012-03-04
 *      Author: naster
 */

#include "Platforma.h"

using namespace std;
using namespace cv;

Platforma::Platforma() :
		error(false) {
	try {
		log = new Log();
	} catch (string &str) {
		cout << str;
		error = true;
	}

	SDL_Init(SDL_INIT_EVERYTHING);
	this->screen = SDL_SetVideoMode(WIDTH, HEIGHT, 32, SDL_DOUBLEBUF);
	SDL_WM_SetCaption("Platforma wizyjna", "Platforma wizyjna");
	engine = new Engine();
	camera = cvCaptureFromCAM(-1);
	opt = new Options();
	if (!camera) {
		cerr << "Błąd kamery" << endl;
		log->Error("Błąd kamery! Nie wykryto podłączonego urządzenia");
		error = true;
	}
	if (TTF_Init() == -1) {
		cerr << "Błąd TTF_Init" << endl;
		log->Error("Błąd biblioteki SDL_ttf. TTF_Init()");
		error = true;
	}
	font = TTF_OpenFont("console.ttf", 12);
	if (font == NULL) {
		cout << "Błąd, nie odnaleziono pliku z czcionką" << endl;
		log->Error("Brak pliku z wymaganą czcionką");
		error = true;
	}

	try {
		usart = new Usart();
	} catch (string &str) {
		error = true;
		log->Error(str.c_str());
	}

}

Platforma::~Platforma() {
	delete log;
	TTF_CloseFont(font);
	TTF_Quit();
	cvReleaseCapture(&camera);
	SDL_FreeSurface(screen);
	SDL_Quit();
}

void Platforma::Loop(void) {
	SDL_Event event;

	while (event.type != SDL_QUIT) {
		if (SDL_PollEvent(&event)) {
			switch (event.type) {
			case SDL_MOUSEMOTION:
				if (opt->mouse) {
					char buf[100];
					sprintf(buf, "Myszka poruszona o: %5d %5d",
							event.motion.xrel, event.motion.yrel);
					PutText(buf, 0, 13);
					SDL_WarpMouse(WIDTH / 2, HEIGHT / 2);
				}

				break;

			case SDL_KEYDOWN:
				switch (event.key.keysym.sym) {
				case SDLK_ESCAPE:
					SDL_Event quit;
					quit.type = SDL_QUIT;
					SDL_PushEvent(&quit);
					break;

				case SDLK_c:
					opt->mouse = !opt->mouse;
					SDL_Event refresh;
					refresh.type = SDL_USEREVENT;
					SDL_PushEvent(&refresh);
					break;

				default:
					engine->KeyDown(event.key.keysym.sym);
					break;
				}
				break;

			case SDL_KEYUP:
				engine->KeyUp(event.key.keysym.sym);
				break;

			case SDL_QUIT:
				break;

			case SDL_USEREVENT:
				SDL_Surface * black = SDL_CreateRGBSurface(SDL_SWSURFACE,
						screen->w, screen->h, 24, 0xff000000, 0x00ff0000,
						0x0000ff00, 0x00000000);
				SDL_BlitSurface(black, NULL, screen, NULL);
				SDL_FreeSurface(black);
				break;

			}
		} else
			GetNewFrame();
	}
}

void Platforma::GetNewFrame(void) {
	static int start = 0;
	static int frame = 0;
	char buf[100];
	IplImage * image = cvQueryFrame(camera);
	if (image == NULL) {
		cerr << "Błąd wyświetlenia obrazka" << endl;
		log->Warning("Błąd wyświetlanego obrazka");
	} else {
		if (opt->fps) {
			if ((SDL_GetTicks() - start) > 1000) {
				sprintf(buf, "Ilosc klatek: %2d", frame);
				PutText(buf, 0, 0);
				frame = 0;
				start = SDL_GetTicks();
			}
			frame++;
		}
		if (opt->engine) {
			sprintf(buf, "Stan silnika lewego: %4d", engine->EnginePow[LEFT]);
			PutText(buf, 0, 24);
			sprintf(buf, "Stan silnika prawego: %4d", engine->EnginePow[RIGHT]);
			PutText(buf, 0, 36);
		}
		SDL_Surface * img = IplToSurface(image);
		SDL_Rect rect = { WIDTH - img->w - 10, HEIGHT - img->h - 10, img->w,
				img->h };
		SDL_BlitSurface(img, NULL, screen, &rect);
		SDL_FreeSurface(img);

		SDL_Flip(screen);
	}
}

SDL_Surface * Platforma::IplToSurface(IplImage *opencvimg) {
	SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(
			(void*) opencvimg->imageData, opencvimg->width, opencvimg->height,
			opencvimg->depth * opencvimg->nChannels, opencvimg->widthStep,
			0xff0000, 0x00ff00, 0x0000ff, 0);
	return surface;
}

void Platforma::PutText(const char * text, int x, int y) {
	SDL_Surface * msg;
	SDL_Color textColor = { 255, 255, 255 };
	SDL_Color background = { 0, 0, 0 };
	SDL_Rect rect;
	rect.x = x;
	rect.y = y;
	msg = TTF_RenderText_Shaded(this->font, text, textColor, background);
	SDL_BlitSurface(msg, NULL, screen, &rect);
	SDL_FreeSurface(msg);
}
